#include <gtest/gtest.h>
#include <utility/spw_tuple.h>
using namespace spwstd;

class TupleTest: public testing::Test {
protected:
    void SetUp() override {}
    void TearDown() override {}
public:
    spwuti::Tuple<int, float, long> i_f_l{1,1.0f,1}; 
    spwuti::Tuple<int, float> i_f{1,1.0}; 
    spwuti::Tuple<int> i{1};
    spwuti::Tuple<> v;
};

TEST_F(TupleTest, ImplTest) {
    spwuti::TupleImpl_in<int, long, int> a{1,1,3};
    EXPECT_EQ(a.head_, 1);
    EXPECT_EQ(*reinterpret_cast<int*>(&a), 3);
    // EXPECT_EQ(a.tail(), 1);
    spwuti::TupleImpl_in<int, long, float> b{1,1,1.0};
    spwuti::TupleImpl_in<int, long, float> c{1,1,1.0};
    EXPECT_TRUE(b==c);
    spwuti::TupleImpl_in<int, long> d{1,1};
    spwuti::TupleImpl_in<int, long> e{1,1};
    EXPECT_TRUE(d==e);
    spwuti::TupleImpl_in<int> f{1};
    spwuti::TupleImpl_in<int> g{1};
    EXPECT_TRUE(f==g);
    spwuti::TupleImpl_in<int, long, double> dd(b);
    spwuti::TupleImpl_in<int, long, double> ddd = b;
    EXPECT_TRUE(ddd==dd);
}

TEST_F(TupleTest, OperatorTest) {
    // ==
    spwuti::Tuple<> a;
    spwuti::Tuple<> b;
    EXPECT_TRUE(a==b);
    spwuti::Tuple<int, long, float> c{1, 1, 1.0};
    spwuti::Tuple<int, long, float> d{1, 1, 1.0};
    EXPECT_TRUE(c==d);
    spwuti::Tuple<int, float> e{1, 1.0};
    spwuti::Tuple<int, float> f{1, 1.0};
    EXPECT_TRUE(e==f);
    spwuti::Tuple<int> h{1};
    spwuti::Tuple<int> m{1};
    EXPECT_TRUE(h==m);

    EXPECT_FALSE(c==e);
    spwuti::Tuple<int, int> g{1, 1};
    spwuti::Tuple<int, long> k{1, 1};
    EXPECT_FALSE(e==g);
    EXPECT_FALSE(k==g);

    // !=
    // # 当类型数量不匹配
    EXPECT_TRUE(v != i_f_l);
    spwuti::Tuple<int, double, int> i_d_i{1,1.0,1}; 
    // # 必须类型相等，不支持隐式转换
    EXPECT_TRUE(i_d_i != i_f_l);
    spwuti::Tuple<int,double,int> i_d_i2{1,1.1,1};
    EXPECT_TRUE(i_d_i != i_d_i2);
    EXPECT_FALSE(i_d_i != i_d_i);

    // <,<=
    // EXPECT_TRUE(i_d_i < i_f_l);// 编译时报错
    EXPECT_TRUE(i_d_i < i_d_i2);
    EXPECT_TRUE(i_d_i <= i_d_i);
    EXPECT_FALSE(v < v);
    EXPECT_TRUE(v <= v);

    // >,>=
    // EXPECT_TRUE(i_d_i > i_f_l);// 编译时报错
    EXPECT_FALSE(i_d_i > i_d_i2);
    EXPECT_FALSE(i_d_i > i_d_i);
    EXPECT_TRUE(i_d_i >= i_d_i);
    EXPECT_FALSE(v > v);
    EXPECT_TRUE(v >= v);
}

TEST_F(TupleTest, OtherTest) {
// get
    EXPECT_EQ(spwuti::get<0>(i_f_l), 1);
    EXPECT_TRUE((std::is_same<decltype(spwuti::get<0>(i_f_l)), int>::value));

    EXPECT_EQ(spwuti::get<1>(i_f_l), 1.0);
    EXPECT_TRUE((std::is_same<decltype(spwuti::get<1>(i_f_l)), float>::value));

    EXPECT_EQ(spwuti::get<2>(i_f_l), 1);
    EXPECT_TRUE((std::is_same<decltype(spwuti::get<2>(i_f_l)), long>::value));

// a.swap , swap()
    spwuti::Tuple<> v2;
    v2.Swap(v);
    spwuti::Tuple<int, float, long> i_f_l2{2,2.0,2}; 
    i_f_l2.Swap(i_f_l);
    EXPECT_EQ(spwuti::get<1>(i_f_l2), 1.0);
    EXPECT_EQ(spwuti::get<1>(i_f_l), 2.0);
    spwuti::swap(i_f_l2, i_f_l);
    EXPECT_EQ(spwuti::get<1>(i_f_l), 1.0);
    EXPECT_EQ(spwuti::get<1>(i_f_l2), 2.0);

// Make_Tuple
// 类型会退化   
   spwuti::Tuple<int, double, int> i_d_i3 = spwuti::makeTuple(3, 3.0, 3);
   const int& in = 3;
   double du = 3.0;
   const int& in2 = 3;
   auto i_d_i4 = spwuti::makeTuple(in, du, in2);
   EXPECT_TRUE(i_d_i3 == i_d_i4);

   spwuti::Tuple<int, double, long> i_d_l = spwuti::makeTuple(3, 3.0, 3l);
   i_d_l = i_f_l;

   // std::tr1::tuple<int, double, int> a(1, 1.1, 1);
   // std::tr1::tuple<int, float, long> b(1, 1.1f, 1);
   // a = b;

// tie
   int inn;
   double dou;
   int ii;
   spwuti::tie(inn, dou, ii) = i_d_i3;
    EXPECT_EQ(inn, 3);
    EXPECT_EQ(dou, 3.0);
    EXPECT_EQ(ii, 3);
}
